package service

import (
	"bytes"
	"crypto/sha1"
	"encoding/json"
	"encoding/xml"
	"errors"
	"fmt"
	"github.com/tidwall/gjson"
	"io/ioutil"
	"net/http"
	"net/url"
	"strconv"
	"time"
	"vrcm/src/vrcm/app/admin/models"
	liveModel "vrcm/src/vrcm/app/admin/models/live"
	"vrcm/src/vrcm/app/admin/models/we_chat"
	dto "vrcm/src/vrcm/app/admin/service/dto/wechat"
	"vrcm/src/vrcm/common/service"
	ext "vrcm/src/vrcm/envconfig"
)

var client = http.Client{}

type WechatService struct {
	service.Service
}

var secretMap = map[string]string{
	//"wx3c37560e077bcedb": "8eca8e207e9f9c86bd16d2df16e65baa", //开放平台网站
	"wx8698f2da02809b0a": "b362c9d92e588197cafb754ed428ee69", //开放平台网站
	"wx1bac52909885a941": "50c56ca4b585e7d7043831751abc7624", //公众平台公众号
}

// GetAccessToken 获取企业微信token
func (e *WechatService) GetAccessToken(d *dto.WechatReq) (string, error) {
	token, _ := e.Redis.Get(models.WeChatAccessSuiteTokenRedis)
	if len(token) > 0 {
		return token, nil
	}
	var wechatUrl = "https://qyapi.weixin.qq.com/cgi-bin/gettoken"
	params := url.Values{}
	Url, err := url.Parse(wechatUrl)
	if err != nil {
		return "", err
	}
	params.Set("corpid", d.CorpId)
	params.Set("corpsecret", models.CorpSecret)
	Url.RawQuery = params.Encode()
	urlPath := Url.String()
	fmt.Println(urlPath)

	// 获取 request请求
	request, err := http.NewRequest("GET", urlPath, nil)
	if len(ext.ExtConfig.ServiceConfig.VsApiServiceUrl) > 0 {
		request.Header.Set("Authorization", "Bearer "+models.SuperToken)
		request.Header.Set("X-PS-Flag", "")
	} else {
		request.Header.Set("Authorization", "vsnb")
	}
	if err != nil {
		e.Log.Errorf("GetHttpSkip Request Error:", err)
		return "", err
	}
	response, err := client.Do(request)
	if err != nil {
		e.Log.Errorf("GetHttpSkip Response Error:", err)
		return "", err
	}

	defer response.Body.Close()
	body, err := ioutil.ReadAll(response.Body)
	if err != nil {
		e.Log.Errorf("读取响应体失败 error:%s", err)
		return "", err
	}
	result := gjson.Parse(string(body))
	if result.Get("errcode").Int() != 0 {
		return "", errors.New(result.Get("errmsg").String())
	}

	token = result.Get("access_token").String()
	err = e.Redis.Set(models.WeChatAccessSuiteTokenRedis, token, 7200)
	if err != nil {
		e.Log.Errorf("设置token缓存失败 error:%s", err)
		return "", err
	}
	return token, nil
}

func (e *WechatService) GetDataCallBack(d *dto.GetWechatCallBack) (interface{}, error) {
	data := 0
	now := time.Now().Unix()
	var xmlData dto.WechatCallBackRes
	wxcpt := NewWXBizMsgCrypt(models.WeChatToken, models.EncodingAESKey, models.CorpId, XmlType)
	//验证消息体签名的正确性
	echoStr, cryptErr := wxcpt.VerifyURL(d.MsgSignature, d.Timestamp, d.Nonce, d.Echostr)
	if nil != cryptErr {
		e.Log.Errorf("verifyUrl fail", cryptErr)
		return data, nil
	}

	if d.Method == "GET" {
		data, _ = strconv.Atoi(string(echoStr))
	} else {
		suite, _ := e.Redis.Get(models.WeChatAccessSuiteTicketRedis)
		if len(suite) > 0 {
			//更新token
			e.GetSuiteAccessToken()
			return data, nil
		}

		var record we_chat.WeChatRecord
		err := e.Orm.Model(we_chat.WeChatRecord{}).Where("1=1").Find(&record).Error

		if err != nil {
			e.Log.Errorf("get WeChatRecord fail", err)
			return data, nil
		}
		//如果凭证没有超过2小时可以直接使用
		if record.Id > 0 && record.UpdateTime+600 > now {
			//设置SuiteTicket 缓存
			err = e.Redis.Set(models.WeChatAccessSuiteTicketRedis, record.SuiteTicket, 600)
			if err != nil {
				e.Log.Errorf("redis set", err)
				return data, err
			}
			//更新token
			e.GetSuiteAccessToken()
			return data, nil
		}
		if len(echoStr) > 0 {
			err = xml.Unmarshal(echoStr, &xmlData)
			if err != nil {
				fmt.Println(err)
				e.Log.Errorf("xml fail", err)
				return data, nil
			}
		}

		if len(xmlData.SuiteTicket) <= 0 {
			return string(echoStr), nil
		}
		//存储SuiteTicket
		r := we_chat.WeChatRecord{
			SuiteTicket: xmlData.SuiteTicket,
		}

		r.CreateTime = now
		r.UpdateTime = now
		err = e.Orm.Model(we_chat.WeChatRecord{}).Where("1=1").Delete(we_chat.WeChatRecord{}).Error
		if err != nil {
			e.Log.Errorf("delete WeChatRecord", err)
			return data, err
		}
		err = e.Orm.Model(we_chat.WeChatRecord{}).Create(&r).Error
		if err != nil {
			e.Log.Errorf("insert WeChatRecord", err)
			return data, err
		}
		//设置SuiteTicket 缓存
		err = e.Redis.Set(models.WeChatAccessSuiteTicketRedis, xmlData.SuiteTicket, 600)
		if err != nil {
			e.Log.Errorf("redis set", err)
			return data, err
		}
		//更新token
		e.GetSuiteAccessToken()
		return string(echoStr), nil
	}

	if d.InfoType == "create_auth" {
		suite, _ := e.Redis.Get(models.WeChatAccessSuiteTicketRedis)
		e.GetPermanentCode(&dto.GetPermanentCode{SuiteAccessToken: suite, AuthCode: d.AuthCode})
	}

	return data, nil
}

func (e *WechatService) GetDataCallBackForScan(d *dto.GetWechatCallBack) (interface{}, error) {
	data := 0
	//now := time.Now().Unix()
	var xmlData dto.WechatCallBackRes
	wxcpt := NewWXBizMsgCrypt(models.WeChatToken, models.EncodingAESKey, models.CorpId, XmlType)
	//验证消息体签名的正确性
	echoStr, cryptErr := wxcpt.VerifyURL(d.MsgSignature, d.Timestamp, d.Nonce, d.Echostr)
	if nil != cryptErr {
		e.Log.Errorf("verifyUrl fail", cryptErr)
		return data, nil
	}
	e.Log.Trace("GetDataCallBackForScan", d.Method)
	if d.Method == "GET" {
		data, _ = strconv.Atoi(string(echoStr))
	} else {
		suite, _ := e.Redis.Get(models.WeChatAccessSuiteTicketForScanRedis)
		if len(suite) > 0 {
			//更新token
			e.GetSuiteAccessTokenForScan()
			return data, nil
		}
		if len(echoStr) > 0 {
			err := xml.Unmarshal(echoStr, &xmlData)
			if err != nil {
				fmt.Println(err)
				e.Log.Errorf("xml fail", err)
				return data, nil
			}
		}
		if len(xmlData.SuiteTicket) <= 0 {
			return string(echoStr), nil
		}

		//设置SuiteTicket 缓存
		err := e.Redis.Set(models.WeChatAccessSuiteTicketForScanRedis, xmlData.SuiteTicket, 600)
		if err != nil {
			e.Log.Errorf("redis set", err)
			return data, err
		}
		//更新token
		e.GetSuiteAccessTokenForScan()
		return string(echoStr), nil
	}

	return data, nil
}

func (e *WechatService) GetSuiteTicket(d *dto.GetWechatCallBack) (string, error) {
	wxcpt := NewWXBizMsgCrypt(models.WeChatToken, models.EncodingAESKey, models.CorpId, XmlType)
	//验证消息体签名的正确性
	echoStr, cryptErr := wxcpt.VerifyURL(d.MsgSignature, d.Timestamp, d.Nonce, d.Echostr)
	if nil != cryptErr {
		e.Log.Errorf("verifyUrl fail", cryptErr)
	}
	return string(echoStr), nil
}

// GetSuiteAccessToken 获取企业微信token
func (e *WechatService) GetSuiteAccessToken() (string, error) {
	//now := time.Now().Unix()
	token, _ := e.Redis.Get(models.WeChatAccessSuiteTokenRedis)
	if len(token) > 0 {
		return token, nil
	}

	wechatUrl := "https://qyapi.weixin.qq.com/cgi-bin/service/get_suite_token"
	// 参数
	data := make(map[string]interface{})
	data["suite_id"] = models.AgentId
	data["suite_secret"] = models.CorpSecret

	suite, _ := e.Redis.Get(models.WeChatAccessSuiteTicketRedis)
	fmt.Println(suite)
	if len(suite) > 0 {
		data["suite_ticket"] = suite
	} else {
		var r we_chat.WeChatRecord
		e.Orm.Model(we_chat.WeChatRecord{}).Where("1=1").Find(&r)
		data["suite_ticket"] = r.SuiteTicket
	}

	// Marshal
	bytesData, _ := json.Marshal(data)

	// 获取 request请求
	request, err := http.NewRequest("POST", wechatUrl, bytes.NewReader(bytesData))
	if len(ext.ExtConfig.ServiceConfig.VsApiServiceUrl) > 0 {
		request.Header.Set("Authorization", "Bearer "+models.SuperToken)
		request.Header.Set("X-PS-Flag", "")
	} else {
		request.Header.Set("Authorization", "vsnb")
	}
	if err != nil {
		e.Log.Errorf("GetHttpSkip Request Error:", err)
		return "", err
	}

	response, err := client.Do(request)
	if err != nil {
		e.Log.Errorf("GetHttpSkip Response Error:", err)
		return "", err
	}

	defer response.Body.Close()
	body, err := ioutil.ReadAll(response.Body)
	if err != nil {
		e.Log.Errorf("读取响应体失败 error:%s", err)
		return "", err
	}
	fmt.Println(string(body))
	e.Log.Trace(string(body))
	result := gjson.Parse(string(body))
	if result.Get("errcode").Int() != 0 {
		return "", errors.New(result.Get("errmsg").String())
	}

	token = result.Get("suite_access_token").String()
	err = e.Redis.Set(models.WeChatAccessSuiteTokenRedis, token, 7200)
	if err != nil {
		e.Log.Errorf("设置token缓存失败 error:%s", err)
		return "", err
	}
	return token, nil
}

func (e *WechatService) GetSuiteAccessTokenForScan() (string, error) {
	//now := time.Now().Unix()
	token, _ := e.Redis.Get(models.WeChatAccessSuiteForScanTokenRedis)
	if len(token) > 0 {
		return token, nil
	}

	wechatUrl := "https://qyapi.weixin.qq.com/cgi-bin/service/get_suite_token"
	// 参数
	data := make(map[string]interface{})
	data["suite_id"] = models.AgentIdForScan
	data["suite_secret"] = models.CorpSecretForScan

	suite, _ := e.Redis.Get(models.WeChatAccessSuiteTicketForScanRedis)
	e.Log.Trace("WeChatAccessSuiteTicketForScanRedis:", suite, models.AgentIdForScan, models.CorpSecretForScan)
	if len(suite) > 0 {
		data["suite_ticket"] = suite
	}

	// Marshal
	bytesData, _ := json.Marshal(data)

	// 获取 request请求
	request, err := http.NewRequest("POST", wechatUrl, bytes.NewReader(bytesData))
	if len(ext.ExtConfig.ServiceConfig.VsApiServiceUrl) > 0 {
		request.Header.Set("Authorization", "Bearer "+models.SuperToken)
		request.Header.Set("X-PS-Flag", "")
	} else {
		request.Header.Set("Authorization", "vsnb")
	}
	if err != nil {
		e.Log.Errorf("GetHttpSkip Request Error:", err)
		return "", err
	}

	response, err := client.Do(request)
	if err != nil {
		e.Log.Errorf("GetHttpSkip Response Error:", err)
		return "", err
	}

	defer response.Body.Close()
	body, err := ioutil.ReadAll(response.Body)
	if err != nil {
		e.Log.Errorf("读取响应体失败 error:%s", err)
		return "", err
	}
	fmt.Println(string(body))
	e.Log.Trace(string(body))
	result := gjson.Parse(string(body))
	if result.Get("errcode").Int() != 0 {
		return "", errors.New(result.Get("errmsg").String())
	}

	token = result.Get("suite_access_token").String()
	err = e.Redis.Set(models.WeChatAccessSuiteForScanTokenRedis, token, 7200)
	if err != nil {
		e.Log.Errorf("设置token缓存失败 error:%s", err)
		return "", err
	}
	return token, nil
}

// GetProviderToken  获取供应商token
func (e *WechatService) GetProviderToken() (string, error) {
	token, _ := e.Redis.Get(models.ProviderAccessTokenRedis)
	if len(token) > 0 {
		return token, nil
	}
	wechatUrl := "https://qyapi.weixin.qq.com/cgi-bin/service/get_provider_token"
	// 参数
	data := make(map[string]interface{})
	data["corpid"] = models.CorpId
	data["provider_secret"] = models.ProviderSecret

	// Marshal
	bytesData, _ := json.Marshal(data)

	// 获取 request请求
	request, err := http.NewRequest("POST", wechatUrl, bytes.NewReader(bytesData))
	if len(ext.ExtConfig.ServiceConfig.VsApiServiceUrl) > 0 {
		request.Header.Set("Authorization", "Bearer "+models.SuperToken)
		request.Header.Set("X-PS-Flag", "")
	} else {
		request.Header.Set("Authorization", "vsnb")
	}
	if err != nil {
		e.Log.Errorf("GetHttpSkip Request Error:", err)
		return "", err
	}
	response, err := client.Do(request)
	if err != nil {
		e.Log.Errorf("GetHttpSkip Response Error:", err)
		return "", err
	}

	defer response.Body.Close()
	body, err := ioutil.ReadAll(response.Body)
	if err != nil {
		e.Log.Errorf("读取响应体失败 error:%s", err)
		return "", err
	}
	fmt.Println(string(body))
	result := gjson.Parse(string(body))
	if result.Get("errcode").Int() != 0 {
		return "", errors.New(result.Get("errmsg").String())
	}

	token = result.Get("provider_access_token").String()
	err = e.Redis.Set(models.ProviderAccessTokenRedis, token, 7200)
	if err != nil {
		e.Log.Errorf("设置token缓存失败 error:%s", err)
		return "", err
	}
	return token, nil
}

// GetPreCode  获取预授权码
func (e *WechatService) GetPreCode(d *dto.GetPreCode) (string, error) {
	wechatUrl := "https://qyapi.weixin.qq.com/cgi-bin/service/get_pre_auth_code"
	params := url.Values{}
	Url, err := url.Parse(wechatUrl)
	if err != nil {
		return "", err
	}
	params.Set("suite_access_token", d.SuiteAccessToken)
	Url.RawQuery = params.Encode()
	urlPath := Url.String()

	fmt.Println(urlPath)

	// 获取 request请求
	request, err := http.NewRequest("GET", urlPath, nil)
	if err != nil {
		e.Log.Errorf("GetHttpSkip Request Error:", err)
		return "", err
	}
	response, err := client.Do(request)
	if err != nil {
		e.Log.Errorf("GetHttpSkip Response Error:", err)
		return "", err
	}

	defer response.Body.Close()
	body, err := ioutil.ReadAll(response.Body)
	if err != nil {
		e.Log.Errorf("读取响应体失败 error:%s", err)
		return "", err
	}
	result := gjson.Parse(string(body))
	if result.Get("errcode").Int() != 0 {
		return "", errors.New(result.Get("errmsg").String())
	}

	token := result.Get("pre_auth_code").String()
	return token, nil
}

// GetPermanentCode  获取永久授权码
func (e *WechatService) GetPermanentCode(d *dto.GetPermanentCode) (*dto.GetPermanentCodeRes, error) {

	wechatUrl := "https://qyapi.weixin.qq.com/cgi-bin/service/get_permanent_code"
	params := url.Values{}
	Url, err := url.Parse(wechatUrl)
	if err != nil {
		return nil, err
	}
	params.Set("suite_access_token", d.SuiteAccessToken)
	Url.RawQuery = params.Encode()
	urlPath := Url.String()

	// 参数
	data := make(map[string]interface{})
	data["auth_code"] = d.AuthCode

	// Marshal
	bytesData, _ := json.Marshal(data)
	// 获取 request请求
	request, err := http.NewRequest("POST", urlPath, bytes.NewReader(bytesData))
	if err != nil {
		e.Log.Errorf("GetHttpSkip Request Error:", err)
		return nil, err
	}
	response, err := client.Do(request)
	if err != nil {
		e.Log.Errorf("GetHttpSkip Response Error:", err)
		return nil, err
	}

	defer response.Body.Close()
	body, err := ioutil.ReadAll(response.Body)
	if err != nil {
		e.Log.Errorf("读取响应体失败 error:%s", err)
		return nil, err
	}
	result := gjson.Parse(string(body))
	if result.Get("errcode").Int() != 0 {
		return nil, errors.New(result.Get("errmsg").String())
	}

	fmt.Println(string(body))
	res := &dto.GetPermanentCodeRes{}
	token := result.Get("permanent_code").String()
	res.PermanentCode = token
	res.CorpId = result.Get("auth_corp_info").Get("corpid").String()
	res.AgentId = result.Get("auth_info").Get("agent.0.agentid").Int()
	key := models.PermanentCodeRedis + models.Delimiter + res.CorpId
	agentKey := models.PermanentAgentIdRedis + models.Delimiter + res.CorpId
	err = e.Redis.Set(key, res.PermanentCode, -1)
	if err != nil {
		e.Log.Errorf("设置永久码缓存失败 error:%s", err)
		return nil, err
	}

	err = e.Redis.Set(agentKey, res.AgentId, -1)
	if err != nil {
		e.Log.Errorf("设置永久码缓存失败 error:%s", err)
		return nil, err
	}

	err = e.Orm.Model(&liveModel.LiveBasic{}).Where("corp_id_secret=?", res.CorpId).Update("permanent_code", res.PermanentCode).Error
	if err != nil {
		e.Log.Errorf("update LiveBasic error:%s", err)
		return nil, err
	}

	return res, nil
}

// GetCorpToken  获取企业凭证
func (e *WechatService) GetCorpToken(d *dto.GetCorpToken) (string, error) {

	key := models.CropTokenRedis + models.Delimiter + d.CorpId
	token, _ := e.Redis.Get(key)
	if len(token) > 0 {
		return token, nil
	}
	wechatUrl := "https://qyapi.weixin.qq.com/cgi-bin/service/get_corp_token"
	params := url.Values{}
	Url, err := url.Parse(wechatUrl)
	if err != nil {
		return "", err
	}
	params.Set("suite_access_token", d.SuiteAccessToken)
	Url.RawQuery = params.Encode()
	urlPath := Url.String()

	fmt.Println(wechatUrl)

	// 参数
	data := make(map[string]interface{})
	data["auth_corpid"] = d.CorpId
	data["permanent_code"] = d.PermanentCode

	// Marshal
	bytesData, _ := json.Marshal(data)
	// 获取 request请求
	request, err := http.NewRequest("POST", urlPath, bytes.NewReader(bytesData))
	if err != nil {
		e.Log.Errorf("GetHttpSkip Request Error:", err)
		return "", err
	}
	response, err := client.Do(request)
	if err != nil {
		e.Log.Errorf("GetHttpSkip Response Error:", err)
		return "", err
	}

	defer response.Body.Close()
	body, err := ioutil.ReadAll(response.Body)
	if err != nil {
		e.Log.Errorf("读取响应体失败 error:%s", err)
		return "", err
	}
	result := gjson.Parse(string(body))
	if result.Get("errcode").Int() != 0 {
		return "", errors.New(result.Get("errmsg").String())
	}

	token = result.Get("access_token").String()
	err = e.Redis.Set(key, token, 7200)
	if err != nil {
		e.Log.Errorf("设置token缓存失败 error:%s", err)
		return "", err
	}
	return token, nil
}

func (e *WechatService) GetCorpTokenCache(d *dto.GetCorpToken) (*dto.GetCorpTokenRes, error) {

	res := &dto.GetCorpTokenRes{}
	agentKey := models.PermanentAgentIdRedis + models.Delimiter + d.CorpId
	agentId, _ := e.Redis.Get(agentKey)
	res.AgentId = agentId

	key := models.CropTokenRedis + models.Delimiter + d.CorpId
	token, _ := e.Redis.Get(key)
	if len(token) > 0 {
		res.CorpToken = token
		return res, nil
	}

	//获取授权码
	permanentCode, _ := e.Redis.Get(models.PermanentCodeRedis + models.Delimiter + d.CorpId)
	if len(permanentCode) <= 0 {
		return res, nil
	}

	//获取suiteAccessToken
	suiteAccessToken, _ := e.Redis.Get(models.WeChatAccessSuiteTokenRedis)
	if len(suiteAccessToken) <= 0 {
		return res, nil
	}

	req := dto.GetCorpToken{}
	req.SuiteAccessToken = suiteAccessToken
	req.CorpId = d.CorpId
	req.PermanentCode = permanentCode

	//获取企业token
	token, err := e.GetCorpToken(&req)
	if err != nil {
		e.Log.Errorf("获取企业token失败 error:%s", err)
		return res, err
	}

	err = e.Redis.Set(key, token, 7200)
	if err != nil {
		e.Log.Errorf("设置企业token缓存失败 error:%s", err)
		return res, err
	}
	return res, nil
}

func (e *WechatService) GetApiTicket(d *dto.GetApiTicket) (string, error) {

	key := models.AgentTicketRedis + models.Delimiter + d.CorpId
	token, _ := e.Redis.Get(key)
	if len(token) > 0 {
		return token, nil
	}
	wechatUrl := "https://qyapi.weixin.qq.com/cgi-bin/ticket/get"
	params := url.Values{}
	Url, err := url.Parse(wechatUrl)
	if err != nil {
		return "", err
	}
	params.Set("access_token", d.CorpToken)
	params.Set("type", "agent_config")
	Url.RawQuery = params.Encode()
	urlPath := Url.String()

	// 获取 request请求
	request, err := http.NewRequest("GET", urlPath, nil)
	if err != nil {
		e.Log.Errorf("GetHttpSkip Request Error:", err)
		return "", err
	}
	response, err := client.Do(request)
	if err != nil {
		e.Log.Errorf("GetHttpSkip Response Error:", err)
		return "", err
	}

	defer response.Body.Close()
	body, err := ioutil.ReadAll(response.Body)
	if err != nil {
		e.Log.Errorf("读取响应体失败 error:%s", err)
		return "", err
	}
	result := gjson.Parse(string(body))
	if result.Get("errcode").Int() != 0 {
		return "", errors.New(result.Get("errmsg").String())
	}

	token = result.Get("ticket").String()
	err = e.Redis.Set(key, token, 7200)
	if err != nil {
		e.Log.Errorf("设置token缓存失败 error:%s", err)
		return "", err
	}
	return token, nil
}

func (e *WechatService) GetApiTicketWithoutType(d *dto.GetApiTicket) (string, error) {

	key := models.AgentTicketWithoutTypeRedis + models.Delimiter + d.CorpId
	token, _ := e.Redis.Get(key)
	if len(token) > 0 {
		return token, nil
	}
	wechatUrl := "https://qyapi.weixin.qq.com/cgi-bin/ticket/get"
	params := url.Values{}
	Url, err := url.Parse(wechatUrl)
	if err != nil {
		return "", err
	}
	params.Set("access_token", d.CorpToken)
	Url.RawQuery = params.Encode()
	urlPath := Url.String()

	fmt.Println(urlPath)

	// 获取 request请求
	request, err := http.NewRequest("GET", urlPath, nil)
	if err != nil {
		e.Log.Errorf("GetHttpSkip Request Error:", err)
		return "", err
	}
	response, err := client.Do(request)
	if err != nil {
		e.Log.Errorf("GetHttpSkip Response Error:", err)
		return "", err
	}

	defer response.Body.Close()
	body, err := ioutil.ReadAll(response.Body)
	if err != nil {
		e.Log.Errorf("读取响应体失败 error:%s", err)
		return "", err
	}
	result := gjson.Parse(string(body))
	if result.Get("errcode").Int() != 0 {
		return "", errors.New(result.Get("errmsg").String())
	}

	token = result.Get("ticket").String()
	err = e.Redis.Set(key, token, 7200)
	if err != nil {
		e.Log.Errorf("设置token缓存失败 error:%s", err)
		return "", err
	}
	return token, nil
}

func (e *WechatService) GetSignature(d *dto.GetSignature) *dto.GetSignatureRes {
	str := "jsapi_ticket=%s&noncestr=%s&timestamp=%s&url=%s"
	//nonceStr := util.NonceStr()
	//t := time.Now().Unix()
	str = fmt.Sprintf(str, d.ApiTicket, d.Nonce, d.Timestamp, d.Url)
	fmt.Println(str)
	sha := sha1.New()
	sha.Write([]byte(str))
	signature := fmt.Sprintf("%x", sha.Sum(nil))
	r := &dto.GetSignatureRes{}
	r.ApiTicket = d.ApiTicket
	r.NonceStr = d.Nonce
	r.Timestamp = d.Timestamp
	r.Url = d.Url
	r.Signature = signature
	return r
}

func (e *WechatService) GetLoginInfo(d *dto.GetLoginInfo) (*dto.LogInfo, error) {

	wechatUrl := "https://qyapi.weixin.qq.com/cgi-bin/service/get_login_info"
	params := url.Values{}
	Url, err := url.Parse(wechatUrl)
	if err != nil {
		return nil, err
	}
	params.Set("access_token", d.ProvideAccessToken)
	Url.RawQuery = params.Encode()
	urlPath := Url.String()

	fmt.Println(urlPath)

	// 参数
	data := make(map[string]interface{})
	data["auth_code"] = d.AuthCode

	// Marshal
	bytesData, _ := json.Marshal(data)
	// 获取 request请求
	request, err := http.NewRequest("POST", urlPath, bytes.NewReader(bytesData))
	if err != nil {
		e.Log.Errorf("GetHttpSkip Request Error:", err)
		return nil, err
	}
	response, err := client.Do(request)
	if err != nil {
		e.Log.Errorf("GetHttpSkip Response Error:", err)
		return nil, err
	}

	fmt.Println(data)
	defer response.Body.Close()
	body, err := ioutil.ReadAll(response.Body)
	if err != nil {
		e.Log.Errorf("读取响应体失败 error:%s", err)
		return nil, err
	}
	result := gjson.Parse(string(body))
	fmt.Println(string(body))
	if result.Get("errcode").Int() != 0 {
		return nil, errors.New(result.Get("errmsg").String())
	}

	res := dto.LogInfo{}
	err = json.Unmarshal([]byte(result.String()), &res)
	if err != nil {
		e.Log.Errorf("反序列化失败 error:%s", err)
		return nil, err
	}
	return &res, nil
}

func (e *WechatService) GetWeChatInfo() (*dto.GetWeChatInfo, error) {
	r := &dto.GetWeChatInfo{}
	r.AgentId = models.AgentId
	r.AgentIdForScan = models.AgentIdForScan
	return r, nil
}

func (e *WechatService) SetAuthCode(d *dto.SetAuthCode) error {

	wechatUrl := "https://qyapi.weixin.qq.com/cgi-bin/service/set_session_info"
	params := url.Values{}
	Url, err := url.Parse(wechatUrl)
	if err != nil {
		return err
	}
	params.Set("suite_access_token", d.SuiteAccessToken)
	Url.RawQuery = params.Encode()
	urlPath := Url.String()
	fmt.Println(urlPath)

	// 参数
	info := dto.SessionInfo{}
	info.AuthType = d.AuthType
	info.AppId = make([]string, 0, 2)
	data := make(map[string]interface{})
	data["pre_auth_code"] = d.PreAuthCode
	data["session_info"] = info
	bytesData, _ := json.Marshal(data)
	// 获取 request请求
	request, err := http.NewRequest("POST", urlPath, bytes.NewReader(bytesData))
	if err != nil {
		e.Log.Errorf("GetHttpSkip Request Error:", err)
		return err
	}
	response, err := client.Do(request)
	if err != nil {
		e.Log.Errorf("GetHttpSkip Response Error:", err)
		return err
	}

	defer response.Body.Close()
	body, err := ioutil.ReadAll(response.Body)
	if err != nil {
		e.Log.Errorf("读取响应体失败 error:%s", err)
		return err
	}
	result := gjson.Parse(string(body))
	if result.Get("errcode").Int() != 0 {
		return errors.New(result.Get("errmsg").String())
	}

	return nil
}

func (e *WechatService) GetUserInfo(d *dto.GetUserInfo) (*dto.GetUserInfoRes, error) {

	wechatUrl := "https://qyapi.weixin.qq.com/cgi-bin/service/auth/getuserinfo3rd"
	params := url.Values{}
	Url, err := url.Parse(wechatUrl)
	if err != nil {
		return nil, err
	}
	params.Set("suite_access_token", d.SuiteAccessToken)
	params.Set("code", d.Code)
	Url.RawQuery = params.Encode()
	urlPath := Url.String()

	fmt.Println(urlPath)

	// 获取 request请求
	request, err := http.NewRequest("GET", urlPath, nil)
	if err != nil {
		e.Log.Errorf("GetHttpSkip Request Error:", err)
		return nil, err
	}
	response, err := client.Do(request)
	if err != nil {
		e.Log.Errorf("GetHttpSkip Response Error:", err)
		return nil, err
	}

	defer response.Body.Close()
	body, err := ioutil.ReadAll(response.Body)
	if err != nil {
		e.Log.Errorf("读取响应体失败 error:%s", err)
		return nil, err
	}
	result := gjson.Parse(string(body))
	e.Log.Trace("GetUserInfo:", string(body))
	if result.Get("errcode").Int() != 0 {
		return nil, errors.New(result.Get("errmsg").String())
	}

	res := dto.GetUserInfoRes{}
	err = json.Unmarshal([]byte(result.String()), &res)
	if err != nil {
		e.Log.Errorf("反序列化失败 error:%s", err)
		return nil, err
	}
	if len(res.CorpId) > 0 {
		liveBasic := &liveModel.LiveBasic{}
		err = e.Orm.Model(&liveModel.LiveBasic{}).Where("corp_id_secret=? and is_delete=2", res.CorpId).Find(&liveBasic).Error
		if err != nil {
			e.Log.Errorf("get LiveBasic error:%s", err)
			return nil, err
		}
		res.TenantId = liveBasic.TenantId
	}
	return &res, nil
}

func (e *WechatService) GetSpecialUserInfo(d *dto.GetSpecialUserInfo) (*dto.GetSpecialUserInfoRes, error) {

	wechatUrl := "https://qyapi.weixin.qq.com/cgi-bin/service/auth/getuserdetail3rd"
	params := url.Values{}
	Url, err := url.Parse(wechatUrl)
	if err != nil {
		return nil, err
	}
	params.Set("suite_access_token", d.SuiteAccessToken)
	Url.RawQuery = params.Encode()
	urlPath := Url.String()

	fmt.Println(urlPath)

	// 参数
	data := make(map[string]interface{})
	data["user_ticket"] = d.UserTicket

	// Marshal
	bytesData, _ := json.Marshal(data)

	// 获取 request请求
	request, err := http.NewRequest("POST", urlPath, bytes.NewReader(bytesData))
	if err != nil {
		e.Log.Errorf("GetHttpSkip Request Error:", err)
		return nil, err
	}
	response, err := client.Do(request)
	if err != nil {
		e.Log.Errorf("GetHttpSkip Response Error:", err)
		return nil, err
	}

	defer response.Body.Close()
	body, err := ioutil.ReadAll(response.Body)
	if err != nil {
		e.Log.Errorf("读取响应体失败 error:%s", err)
		return nil, err
	}
	result := gjson.Parse(string(body))
	fmt.Println(string(body))
	if result.Get("errcode").Int() != 0 {
		return nil, errors.New(result.Get("errmsg").String())
	}

	res := dto.GetSpecialUserInfoRes{}
	err = json.Unmarshal([]byte(result.String()), &res)
	if err != nil {
		e.Log.Errorf("反序列化失败 error:%s", err)
		return nil, err
	}
	return &res, nil
}

// GetWechatToken  获取微信token
func (e *WechatService) GetWechatToken(d *dto.GetWechatTokenReq) (*dto.AccessTokenInfo, error) {

	res := dto.AccessTokenInfo{}
	tokenKey := "accessToken" + models.Delimiter + d.Code
	token, _ := e.Redis.Get(tokenKey)
	//token未过期直接返回
	if len(token) > 0 {
		err := json.Unmarshal([]byte(token), &res)
		if err != nil {
			e.Log.Errorf("反序列化失败 error:%s", err)
			return nil, err
		}
		return &res, nil
	}
	refreshTokenKey := "refreshToke" + models.Delimiter + d.Code
	refreshToken, _ := e.Redis.Get(refreshTokenKey)
	//token过期  refreshToken未过期 刷新token
	if len(refreshToken) > 0 {
		err := json.Unmarshal([]byte(refreshToken), &res)
		if err != nil {
			e.Log.Errorf("反序列化失败 error:%s", err)
			return nil, err
		}
		res1, err := e.RefreshWechatToken(&dto.RefreshTokenReq{RefreshToken: res.RefreshToken, AppId: models.AppId})
		if err != nil {
			e.Log.Errorf("刷新token失败:%s", err)
			return nil, err
		}
		res = *res1
		return &res, nil
	}

	//创建token
	wechatUrl := "https://api.weixin.qq.com/sns/oauth2/access_token"
	params := url.Values{}
	Url, err := url.Parse(wechatUrl)
	if err != nil {
		return nil, err
	}
	secret := secretMap[d.AppId]
	params.Set("appid", d.AppId)
	params.Set("secret", secret)
	params.Set("code", d.Code)
	Url.RawQuery = params.Encode()
	urlPath := Url.String()
	urlPath = urlPath + "&grant_type=authorization_code"
	fmt.Println(urlPath)

	// 获取 request请求
	request, err := http.NewRequest("GET", urlPath, nil)
	if err != nil {
		e.Log.Errorf("GetHttpSkip Request Error:", err)
		return nil, err
	}
	response, err := client.Do(request)
	if err != nil {
		e.Log.Errorf("GetHttpSkip Response Error:", err)
		return nil, err
	}

	defer response.Body.Close()
	body, err := ioutil.ReadAll(response.Body)
	if err != nil {
		e.Log.Errorf("读取响应体失败 error:%s", err)
		return nil, err
	}
	result := gjson.Parse(string(body))
	err = json.Unmarshal([]byte(result.String()), &res)
	if err != nil {
		e.Log.Errorf("反序列化失败 error:%s", err)
		return nil, err
	}
	if len(res.AccessToken) > 0 {
		err = e.Redis.Set(tokenKey, result.String(), res.ExpiresIn)
		if err != nil {
			e.Log.Errorf("设置token过期时间错误:%s", err)
			return nil, err
		}
	}

	if len(res.RefreshToken) > 0 {
		err = e.Redis.Set(refreshTokenKey, result.String(), 29*24*60*60)
		if err != nil {
			e.Log.Errorf("设置refreshToken过期时间错误:%s", err)
			return nil, err
		}
	}

	return &res, nil
}

// RefreshWechatToken  刷新微信token
func (e *WechatService) RefreshWechatToken(d *dto.RefreshTokenReq) (*dto.AccessTokenInfo, error) {
	wechatUrl := "https://api.weixin.qq.com/sns/oauth2/refresh_token?grant_type=refresh_token"
	params := url.Values{}
	Url, err := url.Parse(wechatUrl)
	if err != nil {
		return nil, err
	}
	params.Set("appid", d.AppId)
	params.Set("refresh_token", d.RefreshToken)
	Url.RawQuery = params.Encode()
	urlPath := Url.String()
	fmt.Println(urlPath)

	// 获取 request请求
	request, err := http.NewRequest("GET", urlPath, nil)
	if err != nil {
		e.Log.Errorf("GetHttpSkip Request Error:", err)
		return nil, err
	}
	response, err := client.Do(request)
	if err != nil {
		e.Log.Errorf("GetHttpSkip Response Error:", err)
		return nil, err
	}

	defer response.Body.Close()
	body, err := ioutil.ReadAll(response.Body)
	if err != nil {
		e.Log.Errorf("读取响应体失败 error:%s", err)
		return nil, err
	}
	result := gjson.Parse(string(body))
	res := dto.AccessTokenInfo{}
	err = json.Unmarshal([]byte(result.String()), &res)
	if err != nil {
		e.Log.Errorf("反序列化失败 error:%s", err)
		return nil, err
	}
	tokenKey := "accessToken" + models.Delimiter + d.Code
	err = e.Redis.Set(tokenKey, result.String(), res.ExpiresIn)
	if err != nil {
		e.Log.Errorf("设置token过期时间错误:%s", err)
		return nil, err
	}

	return &res, nil
}

// GetWechatUserInfo  获取微信获取用户个人信息
func (e *WechatService) GetWechatUserInfo(d *dto.GetWechatUserInfoReq) (*dto.WechatUserInfo, error) {
	wechatUrl := "https://api.weixin.qq.com/sns/userinfo"
	params := url.Values{}
	Url, err := url.Parse(wechatUrl)
	if err != nil {
		return nil, err
	}
	params.Set("access_token", d.AccessToken)
	params.Set("openid", d.OpenId)
	Url.RawQuery = params.Encode()
	urlPath := Url.String()
	//urlPath = urlPath + "&grant_type=authorization_code"
	fmt.Println(urlPath)
	// 获取 request请求
	request, err := http.NewRequest("GET", urlPath, nil)
	if err != nil {
		e.Log.Errorf("GetHttpSkip Request Error:", err)
		return nil, err
	}
	response, err := client.Do(request)
	if err != nil {
		e.Log.Errorf("GetHttpSkip Response Error:", err)
		return nil, err
	}

	defer response.Body.Close()
	body, err := ioutil.ReadAll(response.Body)
	if err != nil {
		e.Log.Errorf("读取响应体失败 error:%s", err)
		return nil, err
	}
	result := gjson.Parse(string(body))
	if result.Get("errcode").Int() != 0 {
		return nil, errors.New(result.Get("errmsg").String())
	}

	info := dto.WechatUserInfo{}
	err = json.Unmarshal([]byte(result.String()), &info)
	if err != nil {
		e.Log.Errorf("获取用户信息失败:", err)
		return nil, err
	}
	return &info, nil
}

// GetWechatShareToken  获取微信分享token
func (e *WechatService) GetWechatShareToken(d *dto.GetWechatTokenReq) (*dto.AccessTokenInfo, error) {

	res := dto.AccessTokenInfo{}
	tokenKey := "shareToken" + models.Delimiter + d.AppId
	token, _ := e.Redis.Get(tokenKey)
	//token未过期直接返回
	if len(token) > 0 {
		err := json.Unmarshal([]byte(token), &res)
		if err != nil {
			e.Log.Errorf("反序列化失败 error:%s", err)
			return nil, err
		}
		return &res, nil
	}

	//创建token
	wechatUrl := "https://api.weixin.qq.com/cgi-bin/token"
	params := url.Values{}
	Url, err := url.Parse(wechatUrl)
	if err != nil {
		return nil, err
	}
	secret := secretMap[d.AppId]
	params.Set("appid", d.AppId)
	params.Set("secret", secret)
	Url.RawQuery = params.Encode()
	urlPath := Url.String()
	urlPath = urlPath + "&grant_type=client_credential"
	e.Log.Trace("GetWechatShareToken", urlPath)

	// 获取 request请求
	request, err := http.NewRequest("GET", urlPath, nil)
	if err != nil {
		e.Log.Errorf("GetHttpSkip Request Error:", err)
		return nil, err
	}
	response, err := client.Do(request)
	if err != nil {
		e.Log.Errorf("GetHttpSkip Response Error:", err)
		return nil, err
	}

	defer response.Body.Close()
	body, err := ioutil.ReadAll(response.Body)
	if err != nil {
		e.Log.Errorf("读取响应体失败 error:%s", err)
		return nil, err
	}
	result := gjson.Parse(string(body))
	e.Log.Trace("GetWechatShareToken", string(body))
	err = json.Unmarshal([]byte(result.String()), &res)
	if err != nil {
		e.Log.Errorf("反序列化失败 error:%s", err)
		return nil, err
	}
	if len(res.AccessToken) > 0 {
		err = e.Redis.Set(tokenKey, result.String(), res.ExpiresIn)
		if err != nil {
			e.Log.Errorf("设置token过期时间错误:%s", err)
			return nil, err
		}
	}

	return &res, nil
}

// GetWechatShareTicket  获取微信分享ticket
func (e *WechatService) GetWechatShareTicket(d *dto.GetWechatTokenReq) (*dto.GetSignatureRes, error) {

	res := &dto.GetSignatureRes{}
	ticket := ""
	//获取分享的token
	tokenInfo, err := e.GetWechatShareToken(d)
	if err != nil {
		return res, err
	}

	e.Log.Trace("获取token", tokenInfo)
	ticketTokenKey := "share_ticket" + models.Delimiter + tokenInfo.AccessToken
	ticket, _ = e.Redis.Get(ticketTokenKey)
	if len(ticket) > 0 {
		return res, nil
	}

	//创建ticket
	wechatUrl := "https://api.weixin.qq.com/cgi-bin/ticket/getticket"
	params := url.Values{}
	Url, err := url.Parse(wechatUrl)
	if err != nil {
		return res, err
	}
	params.Set("access_token", tokenInfo.AccessToken)
	params.Set("type", "jsapi")
	Url.RawQuery = params.Encode()
	urlPath := Url.String()
	e.Log.Trace("GetWechatShareTicket", urlPath)

	// 获取 request请求
	request, err := http.NewRequest("GET", urlPath, nil)
	if err != nil {
		e.Log.Errorf("GetHttpSkip Request Error:", err)
		return res, err
	}
	response, err := client.Do(request)
	if err != nil {
		e.Log.Errorf("GetHttpSkip Response Error:", err)
		return res, err
	}

	defer response.Body.Close()
	body, err := ioutil.ReadAll(response.Body)
	if err != nil {
		e.Log.Errorf("读取响应体失败 error:%s", err)
		return res, err
	}
	shareTicket := dto.ShareTicket{}
	result := gjson.Parse(string(body))
	e.Log.Trace("GetWechatShareTicket", string(body))
	if result.Get("errcode").Int() > 0 {
		e.Log.Errorf("获取ticket失败：", result.Get("errmsg"))
		return res, errors.New(result.Get("errmsg").String())
	}
	err = json.Unmarshal([]byte(result.String()), &shareTicket)
	if err != nil {
		e.Log.Errorf("反序列化失败 error:%s", err)
		return res, err
	}
	res = e.GetSignature(&dto.GetSignature{ApiTicket: shareTicket.Ticket, Url: d.Url, Nonce: d.Nonce, Timestamp: d.Timestamp})
	if len(ticket) > 0 {
		err = e.Redis.Set(ticketTokenKey, ticket, 7200)
		if err != nil {
			e.Log.Errorf("设置tiket缓存错误:%s", err)
			return res, err
		}
	}
	return res, nil
}

// CorpIdToOpenCorpId 加密CorpId
func (e *WechatService) CorpIdToOpenCorpId(d *dto.ToOpenCorpIdReq) (*dto.ToOpenCorpId, error) {
	wechatUrl := "https://qyapi.weixin.qq.com/cgi-bin/service/corpid_to_opencorpid"
	params := url.Values{}
	Url, err := url.Parse(wechatUrl)
	if err != nil {
		return nil, err
	}
	accessToken, _ := e.GetProviderToken()
	params.Set("provider_access_token", accessToken)
	Url.RawQuery = params.Encode()
	urlPath := Url.String()
	e.Log.Trace("CorpIdToOpenCorpId:", urlPath)

	data := make(map[string]interface{})
	data["corpid"] = d.CorpId
	bytesData, _ := json.Marshal(data)
	// 获取 request请求
	request, err := http.NewRequest("POST", urlPath, bytes.NewReader(bytesData))
	if err != nil {
		e.Log.Errorf("GetHttpSkip Request Error:", err)
		return nil, err
	}
	response, err := client.Do(request)
	if err != nil {
		e.Log.Errorf("GetHttpSkip Response Error:", err)
		return nil, err
	}

	defer response.Body.Close()
	body, err := ioutil.ReadAll(response.Body)
	if err != nil {
		e.Log.Errorf("读取响应体失败 error:%s", err)
		return nil, err
	}
	result := gjson.Parse(string(body))
	if result.Get("errcode").Int() != 0 {
		return nil, errors.New(result.Get("errmsg").String())
	}

	info := dto.ToOpenCorpId{}
	err = json.Unmarshal([]byte(result.String()), &info)
	if err != nil {
		e.Log.Errorf("获取用户信息失败:", err)
		return nil, err
	}
	return &info, nil
}
